/**
  ******************************************************************************
  * @file    main.c
    * @author  MCU Software Team
  * @Version V1.2.0
  * @Date    2021-01-11
  * @brief   main function
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "flash.h"    
#include "gpio.h"
#include "main.h"

/* Private variables ---------------------------------------------------------*/
static FLASH_EraseInitTypeDef     sFlashEraseInit;
static uint32_t uiErrorPage;

uint32_t sector_addr_start;
uint32_t sector_addr_end;

//更新相关数数据先写到这个数组里面,然后再一次性写到flash
//uint8_t flash_updata_data[FLASH_SECTOR_SIZE+2];         //更新一个扇区的数据
//uint8_t flash_updata_data[2];                           //更新一个扇区的数据
/* Private function prototypes -----------------------------------------------*/
//从flash中读取存储的更新相关的数据 长度一个扇区

void Flash_read_sector_data(uint32_t addr ,uint8_t * data)
{
    int i;
    uint32_t uint32_t_data;
    HAL_Delay(10);
    for(i=0;i<FLASH_PAGE_SIZE;i+=4)
    {
        uint32_t_data = *(uint32_t*)addr;    //读取flash数据
        interface_union.uint32_t_value=uint32_t_data;
        memcpy(&data[i],interface_union.char4_temp,4);
        addr+=4;
    }
}

//把更新相关的所有数据写入到flash(根据实际替代内部程序)
//0: 成功  其它:失败
char Flash_write_sector_data(uint32_t addr,uint8_t * data)
{
    int i;
    uint8_t FlashStatus = 0;
    
    HAL_Delay(10);
    
    for(i=0;i<FLASH_SECTOR_SIZE;i+=4)
    {
        interface_union.char4_temp[0] = data[i+0];
        interface_union.char4_temp[1] = data[i+1];
        interface_union.char4_temp[2] = data[i+2];
        interface_union.char4_temp[3] = data[i+3];
        //写入数据 32位数据
        FlashStatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,addr,interface_union.uint32_t_value);
        if(FlashStatus != HAL_OK)
        {
            break;
        }
        addr+=4;
    }

    if(FlashStatus != 0)
    {
        DbgPrintf("iap_interface_write_all_updata_data ERR:2\r\n");
        return 2;
    }
    return 0;
}

//擦除存储更新数据flash
//0: 成功  其它:失败
char Flash_erase_sector_data(uint32_t data_addr,uint32_t data_size)
{
    int i;
    uint32_t secpos;
    uint32_t  size;
    HAL_Delay(10);
    
    size = data_size/FLASH_SECTOR_SIZE;              //flsh占多少个扇区
    secpos = data_addr-FLASH_MCU_BASE;               //实际地址
    secpos = secpos/FLASH_SECTOR_SIZE;               //扇区地址
    
    for(i=0;i<size;i++)
    {
        /* 开始删除页数据 */
        sFlashEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;    //页擦除 
        sFlashEraseInit.PageAddress = secpos*FLASH_SECTOR_SIZE+FLASH_MCU_BASE;    //开始擦除地址 必须以512Byte为单位
        sFlashEraseInit.NbPages    =  1;                       //擦除一页
        
        if( HAL_FLASH_Erase(&sFlashEraseInit, &uiErrorPage) != HAL_OK)  //擦除对应的页面
        {
            HAL_FLASH_Error_Handler();
            break;
        }
        secpos++;

    }
    return HAL_OK;
}



/*******************************************************************************
* Function Name  : Flash_updata_sector_data
* Description    : Flash 连续更新一个扇区内的数据 
* Input          : addr: 32位地址，需要4对齐
*          codeflash:  startAddr - 0x00000000    size - 0x3E800
*          dataflash:  startAddr - 0x3E800(DATA_FLASH_ADDR)       size -  0x0800(DATA_FLASH_SIZE)
*                   data: 待写入数据缓存区首地址
*                   data_size: 待写入数据字节长度   不大于一个扇区
* Return         : 0 - 成功，其他  - 错误
*******************************************************************************/
char Flash_updata_sector_data(uint32_t addr,uint8_t* data,uint32_t data_size)
{
    if( data_size > FLASH_SECTOR_SIZE )  //数据大小按照一个扇区来设置
    {
      return 3;  //数据长度超出
    }
    
    //删除addr这一片扇区内的数据
    if(Flash_erase_sector_data(addr,FLASH_SECTOR_SIZE) == 0)
    {
        if(Flash_write_sector_data(addr,data)==0)
        {
            return 0;  //写入成功
        }
        else
        {
            return 2; //写入失败
        }
    }
    else
    {
        return 1;  //擦除失败
    }
}


/* Private user code ---------------------------------------------------------*/

uint8_t FLASH_Byte_Read(uint32_t Address)
{
  return (*((uint8_t *)Address));
}

uint16_t FLASH_HalfWord_Read(uint32_t Address)
{
  return (*((uint16_t *)Address));
}

uint32_t FLASH_Word_Read(uint32_t Address)
{
  return (uint32_t)(READ_REG(*((uint32_t *)Address)));
}
/*****************************************************************************
Function name : Hal_DO_flash_Set
Description: flash 设置 DO绑定 参数
Input: 
Return: NONE 
Notes:
******************************************************************************/
void FLASH_DO_GPIO_Set(union_GPIO_t out_gpio,union_GPIO_t in_gpio,Control_Init_t DO ,uint8_t port_id)
{
    /***********************MCU 系统配置*显示************************************/ 

    uint8_t data [ FLASH_PAGE_SIZE ] = {0};

    uint8_t gpio_h,gpio_l;
           
    FLASH_DO_typedef * DO_data = NULL;

    FLASH_GPIO_typedef * GPIO_data = NULL;
    //读取内存中原来的数据
    Flash_read_sector_data(FLASH_GPIO_ADDRESS_START,(uint8_t*) data );  //gpio配置
    GPIO_data = (FLASH_GPIO_typedef*)data;

    /******************DO 控制输出引脚配置********************************/
    gpio_h = (uint8_t)(DO_REG_Param->DO[port_id].out_gpio>>8);
    gpio_l = (uint8_t)(DO_REG_Param->DO[port_id].out_gpio);

    if ( gpio_h == 0 )
    {
        //mcu 引脚
        GPIO_data->CX32[gpio_l/8].Trait[gpio_l%8].Value = out_gpio.Value;
        //控制模式不变
        GPIO_data->CX32[gpio_l/8].Trait[gpio_l%8].bit.Mode = GPIO_REG_Param->CX32[gpio_l/8].Trait[gpio_l%8].bit.Mode;
    }
    else
    {
        //aw9523 引脚
        GPIO_data->aw9523[gpio_l/16].Trait[gpio_l%16].Value = out_gpio.Value;
        //控制模式不变
        GPIO_data->aw9523[gpio_l/16].Trait[gpio_l%16].bit.Mode = GPIO_REG_Param->aw9523[gpio_l/16].Trait[gpio_l%16].bit.Mode;
    }
    /******************DO 控制输入引脚配置********************************/
    gpio_h = (uint8_t)(DO_REG_Param->DO[port_id].in_gpio>>8);
    gpio_l = (uint8_t)(DO_REG_Param->DO[port_id].in_gpio);

    if ( gpio_h == 0 )
    {
        //mcu 引脚
        GPIO_data->CX32[gpio_l/8].Trait[gpio_l%8].Value = in_gpio.Value;
    }
    else
    {
        //aw9523 引脚
        GPIO_data->aw9523[gpio_l/16].Trait[gpio_l%16].Value = in_gpio.Value;
    }
        
    //保存flash内存数据
    Flash_updata_sector_data(FLASH_DEVICE_ADDRESS_START,(uint8_t*)data,FLASH_PAGE_SIZE);

    /******************DO 控制引脚 编号 配置********************************/

    //读取内存中原来的数据
    Flash_read_sector_data(FLASH_DO_ADDRESS_START,(uint8_t*) data );  //DO 配置

    DO_data = ( FLASH_DO_typedef * )data;

    memcpy(&DO_data->DO[port_id],&DO,sizeof(FLASH_DO_typedef));
    //保存flash内存数据
    Flash_updata_sector_data(FLASH_DEVICE_ADDRESS_START,(uint8_t*)data,FLASH_PAGE_SIZE);
}

/*****************************************************************************
Function name : FLASH_DO_threshold_Set
Description: flash 设置DO 设备启动阈值
Input: 
Return: NONE 
Notes:
******************************************************************************/
void Control_DO_threshold_Set(uint16_t Threshold_H,uint16_t Threshold_L, uint8_t port_id)
{
    
  /***********************MCU 系统配置*显示************************************/ 
    uint8_t flash [ FLASH_PAGE_SIZE ] = {0};
    FLASH_DO_typedef  *Param ;
     
    //读取内存中原来的数据
    Flash_read_sector_data(FLASH_DO_ADDRESS_START,(uint8_t*) flash );
    
    Param = (FLASH_DO_typedef  * )flash ;
    
    Param->DO[port_id].Threshold_H = Threshold_H ;
    Param->DO[port_id].Threshold_L = Threshold_L ;
  
    //保存flash内存数据
    Flash_updata_sector_data(FLASH_DO_ADDRESS_START,(uint8_t*)flash,FLASH_PAGE_SIZE);

    Param = NULL;
}

/*****************************************************************************
Function name : Control_DO_IP_Set
Description: flash 设置DO 设备绑定的IP地址
Input: 
Return: NONE 
Notes:
******************************************************************************/
void Control_DO_IP_Set(uint8_t *IP_data, uint8_t port_id)
{
  /***********************MCU 系统配置*显示************************************/ 
    uint8_t flash [ FLASH_PAGE_SIZE ] = {0};
    FLASH_DO_typedef  *Param ;
     
    //读取内存中原来的数据

    Flash_read_sector_data(FLASH_DO_ADDRESS_START,(uint8_t*) flash );
    Param = (FLASH_DO_typedef  * )flash ;
    
    Param->DO[port_id].IP[0] =  IP_data[0] ;
    Param->DO[port_id].IP[1] =  IP_data[1] ;
    Param->DO[port_id].IP[2] =  IP_data[2] ;
    Param->DO[port_id].IP[3] =  IP_data[3] ;
    //保存flash内存数据
    Flash_updata_sector_data(FLASH_DO_ADDRESS_START,(uint8_t*)flash,FLASH_PAGE_SIZE);
    Param = NULL;
}

void  Hal_aw9523_gpio_flash_init(GPIO_Init_t * gpio_init )
{
    uint8_t i,j;
    /*********************** aw9523引脚配置*显示************************************/  
    i = 0; j= 0;   //P0-0 P0-2 P0-3
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_0,1,0,ENABLE);    //addr0-P0-0  BL8023--O3A
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_1,1,0,ENABLE);    //addr0-P0-1  BL8023--O3B
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_2,1,0,ENABLE);    //addr0-P0-2  BL8023--O4A
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_3,1,0,ENABLE);    //addr0-P0-3  BL8023--O4B
    
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_4,1,0,ENABLE);    //addr0-P0-4  BL8023--O5A
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_5,1,0,ENABLE);    //addr0-P0-5  BL8023--O5B
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_6,1,0,ENABLE);    //addr0-P0-6  BL8023--O6A
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_7,1,0,ENABLE);    //addr0-P0-7  BL8023--O6B
    i = 1; j= 0;   //P1-2
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_0,1,0,ENABLE);  //addr0-P1-0  BL8023--O1A
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_1,1,0,ENABLE);  //addr0-P1-1  BL8023--O1B
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_2,1,0,ENABLE);  //addr0-P1-2  BL8023--O2A
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_3,1,0,ENABLE);  //addr0-P1-3  BL8023--O2B
    
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_4,1,0,ENABLE);  //addr0-P1-4  BL8023--O7A
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_5,1,0,ENABLE);  //addr0-P1-5  BL8023--O7B
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_6,1,0,ENABLE);  //addr0-P1-6  BL8023--O8A
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_7,1,0,ENABLE);  //addr0-P1-7  BL8023--O8B
    
    /*********************** aw9523引脚配置*显示************************************/  
    i = 2; j= 0;   //P0-0 P0-2 P0-3
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_0,1,0,ENABLE);    //addr0-P0-0   OA5  LED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_1,1,0,ENABLE);    //addr0-P0-1   OA6  LED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_2,1,0,ENABLE);    //addr0-P0-2   OA7  LED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_3,1,0,ENABLE);    //addr0-P0-3   OA8  LED
    
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_4,1,0,ENABLE);    //addr0-P0-4
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_5,1,0,ENABLE);    //addr0-P0-5
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_6,1,0,ENABLE);    //addr0-P0-6
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_7,1,0,ENABLE);    //addr0-P0-7
    i = 3; j= 0;   //P1-2
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_0,1,0,ENABLE);  //addr0-P1-0   OA1  LED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_1,1,0,ENABLE);  //addr0-P1-1   OA2  LED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_2,1,0,ENABLE);  //addr0-P1-2   OA3  LED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_3,1,0,ENABLE);  //addr0-P1-3   OA4  LED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_4,1,0,ENABLE);  //addr0-P1-4   OA5
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_5,1,0,ENABLE);  //addr0-P1-5   OA6
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_6,1,0,ENABLE);  //addr0-P1-6   OA7
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],AW9523_MODE_OUTPUT,GPIO_PIN_7,1,0,ENABLE);  //addr0-P1-7   OA8
}

void  Hal_mcu_gpio_flash_init(GPIO_Init_t * gpio_init)
{
    uint8_t i,j;
    /***********************MCU引脚配置*显示************************************/ 
    i = 0; j= 0;   //端口A   
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_0,1,0,DISABLE);  //PA0
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_1,0,0,DISABLE);  //PA1      uart0_rx
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_2,0,0,DISABLE);  //PA2      uart0_tx
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_3,1,0,DISABLE);  //PA3      UART0_EN
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_4,1,1,DISABLE);  //PA4
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_5,1,1,DISABLE);  //PA5
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_6,1,1,DISABLE);  //PA6
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_7,1,1,DISABLE);  //PA7
    i = 1; j= 0; //端口B  
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_0,1,0,DISABLE);  //PB0
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_1,0,0,DISABLE);  //PB1
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_2,0,0,DISABLE);  //PB2
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_3,1,1,DISABLE);  //PB3
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_4,1,0,DISABLE);  //PB4     uart1_rx
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_5,1,1,DISABLE);  //PB5     uart1_tx
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_6,1,1,DISABLE);  //PB6   
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_7,1,1,DISABLE);  //PB7
    i = 2; j= 0;  //端口C
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_0,1,0,DISABLE);  //PC0
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_1,0,0,DISABLE);  //PC1
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_2,0,0,DISABLE);  //PC2
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_3,1,1,DISABLE);  //PC3    IIC_SDA
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_4,1,1,DISABLE);  //PC4    IIC_SCL
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_5,1,1,DISABLE);  //PC5    LPUART_RX
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_6,1,1,DISABLE);  //PC6    LPUART_TX
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_7,1,1,DISABLE);  //PC7    SWDIO       下载口
    i = 3; j= 0; //端口D  
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_0,1,0,DISABLE);  //PD0
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_1,0,0,DISABLE);  //PD1     SWDCLK      下载口
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],GPIO_MODE_OUTPUT,GPIO_PIN_2,0,1,ENABLE);   //PD2  运行灯
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],GPIO_MODE_INPUT,GPIO_PIN_3,0,1,ENABLE);    //PD3  PWR1检测
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],GPIO_MODE_INPUT,GPIO_PIN_4,0,1,ENABLE);    //PD4  PWR2检测
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],GPIO_MODE_OUTPUT,GPIO_PIN_5,0,1,ENABLE);   //PD5  RXLED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],GPIO_MODE_OUTPUT,GPIO_PIN_6,0,1,ENABLE);   //PD6  TXLED
    MCU_GPIO_Parameterize(&gpio_init[i].Trait[j++],0,GPIO_PIN_7,1,1,DISABLE);   //PD7
  
}

void  Hal_gpio_flash_init(uint8_t mode)
{
    FLASH_GPIO_typedef GPIO_data = {0};
    
    if( mode )
    {  
        Hal_mcu_gpio_flash_init(GPIO_data.CX32);
        Hal_aw9523_gpio_flash_init(GPIO_data.aw9523);
        //初始化flash内存数据
        Flash_updata_sector_data(FLASH_GPIO_ADDRESS_START,(uint8_t*)&GPIO_data,FLASH_PAGE_SIZE);
    }
}


void  Hal_DO_flash_init(uint8_t mode)
{
    FLASH_DO_typedef  DO_Init = {0};
    uint16_t DO_type ;
    uint8_t cnt = 0;
    uint8_t ip_add [4] = {0} ;
    if(mode){
        //类型+ 控制+ 检测+ 备注名 
        DO_type =(uint16_t) (DIY_T<<8|cnt );                                                                     
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x010F,0xFFFF,ip_add,"OUT8",ENABLE); //addr0 out:P1-7  /addr1 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );                                                                     
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x010E,0xFFFF,ip_add,"OUT7",ENABLE); //addr0 out:P1-6  /addr1 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );                                                                     
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x010D,0xFFFF,ip_add,"OUT6",ENABLE); //addr0 out:P1-5  /addr1 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x010C,0xFFFF,ip_add,"OUT5",ENABLE); //addr0 out:P1-4  /addr1 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x010B,0xFFFF,ip_add,"OUT4",ENABLE);  //addr0 out:P1-3  /addr1 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );   
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x010A,0xFFFF,ip_add,"OUT3",ENABLE);  //addr0 out:P1-2  /addr1 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x0109,0xFFFF,ip_add,"OUT2",ENABLE);  //addr0 out:P1-1  /addr1 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );  
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x0108,0xFFFF,ip_add,"OUT1",ENABLE);  //addr0 out:P1-0  /addr1 in:NULL     继电器

                            
        /********************************************扩展板子*********************************************************/
        //类型+ 控制+ 检测+ 备注名  
        DO_type =(uint16_t) (DIY_T<<8|cnt );  
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x0128,0xFFFF,ip_add,"OUT9",DISABLE);   //addr2 out:P1-0  /addr3 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x0129,0xFFFF,ip_add,"OUT10",DISABLE);   //addr2 out:P1-1  /addr3 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );   
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x012A,0xFFFF,ip_add,"OUT11",DISABLE);  //addr2 out:P1-2  /addr3 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x012B,0xFFFF,ip_add,"OUT12",DISABLE);  //addr2 out:P1-3  /addr3 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x0120,0xFFFF,ip_add,"OUT13",DISABLE); //addr2 out:P0-0  /addr3 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x0121,0xFFFF,ip_add,"OUT14",DISABLE); //addr2 out:P0-1  /addr3 in:NULL1     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x0122,0xFFFF,ip_add,"OUT15",DISABLE); //addr2 out:P0-2  /addr3 in:NULL     继电器
        DO_type =(uint16_t) (DIY_T<<8|cnt );
        Control_Parameterize(&DO_Init.DO[cnt++],DO_type,DC12V_t,
                            0x0123,0xFFFF,ip_add,"OUT16",DISABLE);  //addr2 out:P0-3  /addr3 in:NULL     继电器
        //初始化flash内存数据
        Flash_updata_sector_data(FLASH_DO_ADDRESS_START,(uint8_t*)&DO_Init,FLASH_PAGE_SIZE);
    }
}


void  Hal_DI_flash_init(uint8_t mode)
{
    FLASH_DI_typedef    DI_Init = {0};
    uint16_t DI_type = 0;
    uint8_t cnt = 0;
    if(mode)
    {
        //类型+ 控制+ 检测+ 备注名 
        DI_type =(uint16_t) (Power_T<<8|cnt );  //220V断电检测
        Input_Parameterize(&DI_Init.DI[cnt++],DI_type,0x001B,"PWR_DET1",ENABLE);  //PD3
        DI_type =(uint16_t) (DIY_T<<8|cnt );    //220v断电检测
        Input_Parameterize(&DI_Init.DI[cnt++],DI_type,0x001C,"PWR_DET2",ENABLE);  //PD4
        DI_type =(uint16_t) (Power_T<<8|cnt ); 
        Input_Parameterize(&DI_Init.DI[cnt++],DI_type,0x03,"WATER_L",DISABLE);  //PC5
        
        DI_type =(uint16_t) (WATER_L<<8|cnt );
        Input_Parameterize(&DI_Init.DI[cnt++],DI_type,0x04,"WATER_L",DISABLE); 
        DI_type =(uint16_t) (WATER_L<<8|cnt );
        Input_Parameterize(&DI_Init.DI[cnt++],DI_type,0x05,"WATER_L",DISABLE);
        DI_type =(uint16_t) (WATER_L<<8|cnt );
        Input_Parameterize(&DI_Init.DI[cnt++],DI_type,0x06,"WATER_L",DISABLE);
        DI_type =(uint16_t) (WATER_L<<8|cnt );
        Input_Parameterize(&DI_Init.DI[cnt++],DI_type,0x07,"WATER_L",DISABLE);
        DI_type =(uint16_t) (WATER_L<<8|cnt );
        Input_Parameterize(&DI_Init.DI[cnt++],DI_type,0x08,"WATER_L",DISABLE);
        //初始化flash内存数据
        Flash_updata_sector_data(FLASH_DI_ADDRESS_START,(uint8_t*)&DI_Init,FLASH_PAGE_SIZE);
    }
}


uint8_t  Hal_mcu_system_flash_init(uint8_t mode)
{
    uint8_t ret = 0;
    uint8_t flash_data [ FLASH_SECTOR_SIZE ] = {0};

    FLASH_EQUIPMENT_typedef  * Param ;
    /***********************MCU 系统配置*显示************************************/ 
    Flash_read_sector_data(FLASH_DEVICE_ADDRESS_START, flash_data );
    Param = (FLASH_EQUIPMENT_typedef  *) flash_data;
    
    if( memcmp( Param->DEVICE.flag,DEVICE_REG_COPY.flag,4 ) || mode) 
    {    
        memset(flash_data,0,FLASH_SECTOR_SIZE);
        //出厂默认配置
        memcpy(&Param->DEVICE,&DEVICE_REG_COPY,sizeof(DEVICE_REG_COPY)); 
        
        memcpy(&Param->NET,&NET_REG_COPY,sizeof(NET_REG_COPY));
        
        memcpy(&Param->POWER,&POWER_REG_COPY,sizeof(POWER_REG_COPY));
        
        memcpy(&Param->BT,&BT_REG_COPY,sizeof(BT_REG_COPY));

        memset(&Param->ALAEM,0,sizeof(CONFIG_ALAEM_REG_t) );
        //初始化flash内存数据
        Flash_updata_sector_data(FLASH_DEVICE_ADDRESS_START,(uint8_t*)Param,FLASH_PAGE_SIZE);
        
        ret = 1;
    }

    return ret;    
}

uint8_t  Hal_BT_REG_flash_init(uint8_t mode)
{
    uint8_t ret = 0;
    uint8_t flash_data [ FLASH_SECTOR_SIZE ] = {0};

    FLASH_BT_typedef  * Param ;
    /***********************MCU 系统配置*显示************************************/ 
    Flash_read_sector_data(FLASH_BT_ADDRESS_START, flash_data );
    
    Param = (FLASH_BT_typedef  *) flash_data;
    
    if( (uint8_t)Param->BT_poleCode[0] == 0xFF  || mode) 
    {    
        memset(flash_data,0,FLASH_SECTOR_SIZE);
        //出厂默认配置
        memcpy(&Param->BT_company,FLASH_BT_REG_COPY.BT_company,strlen(FLASH_BT_REG_COPY.BT_company)); 
        memcpy(&Param->BT_location,FLASH_BT_REG_COPY.BT_location,strlen(FLASH_BT_REG_COPY.BT_location)); 
        memcpy(&Param->BT_poleCode,FLASH_BT_REG_COPY.BT_poleCode,strlen(FLASH_BT_REG_COPY.BT_poleCode)); 
        //初始化flash内存数据
        Flash_updata_sector_data(FLASH_BT_ADDRESS_START,(uint8_t*)Param,FLASH_PAGE_SIZE);
        ret = 1;
    }

    return ret;    
}

uint16_t  Hal_flash_relay_state(uint8_t mode,uint16_t state )
{
    uint16_t relay_state = 0;
    
    uint8_t flash_data [ FLASH_SECTOR_SIZE ] = {0};

    FLASH_EQUIPMENT_typedef  * Param ;
    /***********************MCU 系统配置*显示************************************/ 
    Flash_read_sector_data(FLASH_DEVICE_ADDRESS_START, flash_data );
    Param = (FLASH_EQUIPMENT_typedef  *) flash_data;
    
    if(mode)  //更新
    {
        Param->POWER.relay_state = state;
        
        Flash_updata_sector_data(FLASH_DEVICE_ADDRESS_START,(uint8_t*)Param,FLASH_PAGE_SIZE);
        
        relay_state = state;
        
    }else{   //获取
       relay_state =  Param->POWER.relay_state;
    }
    return relay_state;    
}

void Hal_flash_power_up(uint8_t mode,uint16_t * cfg )
{

    uint8_t flash_data [ FLASH_SECTOR_SIZE ] = {0};
    uint8_t cnt = 0;
    FLASH_EQUIPMENT_typedef  * Param ;
    /***********************MCU 系统配置*显示************************************/ 
    Flash_read_sector_data(FLASH_DEVICE_ADDRESS_START, flash_data );
    Param = (FLASH_EQUIPMENT_typedef  *) flash_data;
    
    if(mode)  //更新
    {
        cnt = 0;
        Param->DEVICE.Address = cfg[cnt++];   //设备地址
      
        if( cfg[cnt] > 5 )  Param->DEVICE.Baud = 0;   //波特率
        else  Param->DEVICE.Baud = cfg[cnt] ;
        
        cnt += 4;  
      
        Param->POWER.OverVol  = cfg[cnt++];   //电源过压告警     阈值 
        Param->POWER.LowVol   = cfg[cnt++];   //电源欠压告警     阈值
        Param->POWER.OverCurr = cfg[cnt++];   //电源过流告警     阈值
        Param->POWER.LeakCurr = cfg[cnt++];   //电源漏电告警     阈值
        
        Flash_updata_sector_data(FLASH_DEVICE_ADDRESS_START,(uint8_t*)Param,FLASH_PAGE_SIZE);
    }else{   //获取
      
        cnt = 0;
      
        cfg[cnt++] = Param->DEVICE.Address;   //设备地址
        cfg[cnt++] = Param->DEVICE.Baud;      //波特率
      
        cnt+=3;
      
        cfg[cnt++] = Param->POWER.OverVol ;   //电源过压告警    阈值 
        cfg[cnt++] = Param->POWER.LowVol  ;   //电源欠压告警    阈值
        cfg[cnt++] = Param->POWER.OverCurr;   //电源过流告警    阈值
        cfg[cnt++] = Param->POWER.LeakCurr;   //电源漏电告警    阈值

    }
    return ;    
}

/*****************************************************************************
Function name : FLASH_INIT
Description: flash 参数初始化
Input: 
Return: NONE 
Notes:
******************************************************************************/
void FLASH_INIT(void)
{
    uint8_t en;
    en = Hal_mcu_system_flash_init(0);   //初始化系统定义    测试状态参数 1 
    Hal_gpio_flash_init(en);             //初始化gpio引脚     
#if TIME_CONTROL_EN    
    Hal_DO_flash_init(en);               //初始化控制类配置   
    Hal_DI_flash_init(en);               //初始化检测类配置   
#endif
    Hal_BT_REG_flash_init(en);           //初始化蓝牙信息

}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void HAL_FLASH_Error_Handler(void)
{
    DbgPrintf("Error Address \n");
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */


/* Private function -------------------------------------------------------*/



